package com.cl.dao;

import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;

import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.cl.entity.CcPay;
import com.cl.entity.CcSync;
import com.cl.entity.Doc;
import com.cl.entity.DocUk;
import com.cl.entity.Image;
import com.cl.entity.Rel;
import com.cl.entity.common.DBObject;
import com.cl.entity.common.DataEntity;
import com.cl.util.ClassNameReplaceUtil;
import com.cl.util.CommonUtil;
import com.cl.util.ReflectionUtil;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;

@Repository
@Transactional(value = "transactionManager", noRollbackFor = {NoResultException.class})
public class CommonDao {

    @PersistenceContext(unitName = "entityManagerFactory")
    private EntityManager entityManager;

    @Autowired
    private CommonUtil commonUtil;
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Value("#{classmappingProperties}")
    private HashMap<String, String> classMapping;
    
    @Value("#{titlefieldProperties}")
    private HashMap<String, String> titlefield;
    
    @Value("#{authorfieldProperties}")
    private HashMap<String, String> authorfield;
    
    @Autowired
    private SearchDao searchDao;

    protected EntityManager getEntityManager() {
        return entityManager;
    }

    /**
     * @param data
     * @return
     */
    public Object saveDBOject(DBObject data) {
        if (data.getPrimaryId() == null) {
            data.setDcCreate(new Date());
            getEntityManager().persist(data);
        } else {
            data.setLastUpdate(new Date());
            getEntityManager().merge(data);
        }
        return data.getPrimaryId();
    }

    public Object saveDBOject(DBObject data, String description, String userId, String ip) {
        CcSync log = new CcSync();
        log.setEn(data.getClass().getName());
        //System.out.println("jjjjjjjjjjjjjjjjjjjjjjjjjjjjj:"+data.getPrimaryId());
        if (data.getPrimaryId() == null) {
            data.setDcCreate(new Date());
            data.setDcEditor0(userId);
            getEntityManager().persist(data);
            //创建一条新的记录
            log.setOper("A");
        } else {
            data.setLastUpdate(new Date());           
            getEntityManager().merge(data);
            // 更新一条已有的记录
            //c4w 3.28 此处代码不应加,无论新增还是修改一条记录,CcSync记录操作日志都应增加一条
            //List li=searchDao.listEntities("com.cl.entity.CcSync", "keyval", String.valueOf(data.getPrimaryId()), 1);//jj0217
            //log=(CcSync) li.get(0);//jj0217
            log.setOper("U");
        }
        log.setKeyval(String.valueOf(data.getPrimaryId()));
        log.setTmCreate(new Date());
        log.setUserid(userId);
        log.setIp(ip);
        log.setDescription(description);
        saveDBOject(log);
        return data.getPrimaryId();
    }

    /**
     * @param entity
     */
    public void deleteDBObject(DBObject entity) {
        this.getEntityManager().remove(entityManager.contains(entity) ? entity : entityManager.merge(entity));
    }

    public void deleteDBObject(DBObject entity, String description, String userId, String ip) {
        this.getEntityManager().remove(entityManager.contains(entity) ? entity : entityManager.merge(entity));
        CcSync log = new CcSync();
        log.setEn(entity.getClass().getName());
        log.setOper("R");
        log.setKeyval(String.valueOf(entity.getPrimaryId()));
        log.setTmCreate(new Date());
        log.setUserid(userId);
        log.setIp(ip);
        log.setDescription(description);
        saveDBOject(log);
    }

    public int delOrgRecord(int status) {
        String hql = "delete from UOrg where status=:status";
        return entityManager.createQuery(hql).setParameter("status", status).executeUpdate();
    }
    
    /**
     * 写入data对应的多条稿酬
     * @param data
     * @param userId
     * @param ip
     * @return
     */
    public void savePays(DBObject data, String userId, String ip){
    	
    	//写入三条稿酬日志
    	String type = data.getClass().getName();//新类型
    	String class_ = classMapping.get(type);//旧类型
    	
    	
		CcPay pay0 = new CcPay(class_, (Long)data.getPrimaryId(), new Date(), "djr");
		String authorId = (String) ReflectionUtil.getValueofClassField(type, data, authorfield.get(type));
		pay0.setAuthorId(authorId);
		String title = (String) ReflectionUtil.getValueofClassField(type, data, titlefield.get(type));
		pay0.setTitle(title);
		savePay(data,pay0,userId,ip);
    	/*CcPay pay1 = new CcPay(class_, (Long)data.getPrimaryId(), new Date(), "ysr");
    	CcPay pay2 = new CcPay(class_, (Long)data.getPrimaryId(), new Date(), "esr");
    	if(type.contains("Uk")){
    		pay1.setWorkitem("wgfyr");
    		pay2.setWorkitem("wwscr");
    	}
    	
    	savePay(data,pay1,userId,ip);
    	savePay(data,pay2,userId,ip);*/
    	
    }
    
    /**
     * 生成一条稿酬并写入关联表和log日志
     * @param pay
     * @return
     */
    @Transactional(readOnly = false)
    public Object savePay(DBObject data, CcPay pay, String userId, String ip)
    {
    	CcSync log = new CcSync();
    	log.setEn(CcPay.class.getName());
    	//写入稿酬
    	getEntityManager().persist(pay);
    	
    	String type = data.getClass().getName();
    	//写入关联表
    	Rel rel = new Rel();
    	rel.setEntity1(type.substring(type.lastIndexOf(".")+1).toUpperCase());
    	rel.setId1((Long)data.getPrimaryId());
    	rel.setEntity2("CCPAY");
    	rel.setId2((Long)pay.getPrimaryId());
    	getEntityManager().persist(rel);
    	
    	//写入log日志
    	log.setOper("A");
    	log.setKeyval(String.valueOf(pay.getPrimaryId()));
        log.setTmCreate(new Date());
        log.setUserid(userId);
        log.setIp(ip);
        log.setDescription(pay.toString());
        saveDBOject(log);
    	
    	return pay.getPrimaryId();
    }
    
    /**
     * 计算更新稿酬
     * @param pay
     * @param userId
     * @param ip
     * @return
     */
    @Transactional(readOnly = false)
    public Object updatePay(CcPay pay, String userId, String ip)
    {
    	CcSync log = new CcSync();
    	log.setEn(CcPay.class.getName());
    	//写入稿酬
    	getEntityManager().merge(pay);
    	//System.out.println("ppppppppppppppppppppppppp:"+pay.getId());
    	//System.out.println("ppppppppppppppppppppppppp:"+pay.getKeyval());
    	//写入log日志
    	log.setOper("U");
    	log.setKeyval(String.valueOf(pay.getPrimaryId()));
        log.setTmCreate(new Date());
        log.setUserid(userId);
        log.setIp(ip);
        log.setDescription(pay.toString());
        saveDBOject(log);
        
        return pay.getPrimaryId();
    }
    
    
    public void deleteRel(Long id1, String entity1, Long id2, String entity2, String userId, String ip)
    {
    	ObjectMapper objectMapper = new ObjectMapper();
    	try {
			Rel rel = new Rel();
			rel.setId1(id1);
			rel.setEntity1(entity1);
			rel.setId2(id2);
			rel.setEntity2(entity2);
			List<Rel> rels = searchDao.getRels(rel);
			if ((rels != null) && (rels.size() > 0)) {
				for (int j = 0; j < rels.size(); j++) {
					deleteDBObject(rels.get(j),
							objectMapper.writeValueAsString(rels.get(j)),
							userId, ip);
				}
			}
		} catch (JsonGenerationException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
    }
    
    /**
     * 保存实体同时更新稿酬日志，根据 登记人、初审、终审 是否为空删除对应稿酬
     * @param data
     * @param userId
     * @param ip
     */
	public void updatePays(DBObject data, String userId, String ip) {
		ObjectMapper objectMapper = new ObjectMapper();

		String type = data.getClass().getName();// 新类型
//jj 11.10		
    	classMapping.put("com.cl.entity.DocUk", "dao.hb.DocUk");
    	
		String class_ = classMapping.get(type);// 旧类型

		boolean hasAuthor = false;
		boolean hasYsr = false;
		boolean hasEsr = false;
		List<CcPay> pays=new ArrayList<CcPay>();
		//删除多余的稿酬日志pay
			String clazz = new ClassNameReplaceUtil().replaceName(class_);//jj1211
			pays = searchDao.getRelPays(clazz, data.getPrimaryId());//jj1211
		
			List<CcPay> pays2 = searchDao.getRelPays(class_, data.getPrimaryId());//jj1211
		for( CcPay cc:pays2){
			pays.add(cc);
		}
		//增加对影像稿酬计算的特殊处理
		if(type.contains("Image")){
			if(pays!=null && pays.size()>0){
				CcPay pay = pays.get(0);
				Image img = (Image) data;
				if(img.getUsage()!=null && img.getUsage().equalsIgnoreCase("集体"))
					pay.setAuthorId("资料信息部");
				else
					pay.setAuthorId(img.getPhotographer());
				pay.setTitle(img.getImageName());
				updatePay(pay,userId,ip);
			}
			return;
		}

		
		/*String entity1 = type.substring(type.lastIndexOf(".")+1).toUpperCase();
		Class payClass = CcPay.class;
		List<CcPay> pays = searchDao.getRelEntities(payClass, "CcPay", (Long) data.getPrimaryId(), entity1, "CCPAY", "id");
*/		
		try {
			DataEntity dataEntity = (DataEntity) data;
			
			String title = (String) ReflectionUtil.getValueofClassField(type, dataEntity, titlefield.get(type));
			String authorId = (String) ReflectionUtil.getValueofClassField(type, data, authorfield.get(type));

			
			for (CcPay pay : pays) {
						
				String workitem = pay.getWorkitem();
				if (StringUtils.isEmpty(workitem))
					continue;
				// djr稿酬
				if (workitem.equalsIgnoreCase("djr")) {
					hasAuthor = true;
					if(StringUtils.isEmpty(authorId)) {
						deleteRel((Long) dataEntity.getPrimaryId(), type
								.substring(type.lastIndexOf(".") + 1)
								.toUpperCase(), pay.getId(), "CCPAY", userId,
								ip);
						deleteDBObject(pay,
								objectMapper.writeValueAsString(pay), userId,
								ip);
					} else {
						if (!class_.contains("Thesis")) {
							if (dataEntity.getDcTxtwords() != null)
								pay.setDocNumber(new BigDecimal(dataEntity
										.getDcTxtwords()));
							}
							if(class_.endsWith("Doc")){
								pay.setSubtype(((Doc)dataEntity).getSubtype());
							}
							if(class_.endsWith("DocUk")){
								pay.setSubtype(((DocUk)dataEntity).getSubtype());
							}
							
							pay.setAuthorId(authorId);
							pay.setTitle(title);
							updatePay(pay, userId, ip);
						
					}
					continue;
				}
				
				if (workitem.equalsIgnoreCase("ysr")
						|| workitem.equalsIgnoreCase("wgfyr")) {
					hasYsr = true;
					if(StringUtils.isEmpty(dataEntity.getDcEditor1())) {
						deleteRel((Long) dataEntity.getPrimaryId(), type
								.substring(type.lastIndexOf(".") + 1)
								.toUpperCase(), pay.getId(), "CCPAY", userId,
								ip);
						deleteDBObject(pay,
								objectMapper.writeValueAsString(pay), userId,
								ip);
					} else {
						if (!class_.contains("Thesis")) {
							if (dataEntity.getDcTxtwords() != null)
								pay.setDocNumber(new BigDecimal(dataEntity
										.getDcTxtwords()));
							}
							if(class_.endsWith("Doc")){
								pay.setSubtype(((Doc)dataEntity).getSubtype());
							}
							if(class_.endsWith("DocUk")){
								pay.setSubtype(((DocUk)dataEntity).getSubtype());
							}
							pay.setAuthorId(dataEntity.getDcEditor1());
							pay.setTitle(title);
							updatePay(pay, userId, ip);
						
					}
					continue;
				}
				if (workitem.equalsIgnoreCase("esr")
						|| workitem.equalsIgnoreCase("wwscr")) {
					hasEsr = true;
					if(StringUtils.isEmpty(dataEntity.getDcEditor2())) {
						deleteRel((Long) dataEntity.getPrimaryId(), type
								.substring(type.lastIndexOf(".") + 1)
								.toUpperCase(), pay.getId(), "CCPAY", userId,
								ip);
						deleteDBObject(pay,
								objectMapper.writeValueAsString(pay), userId,
								ip);
					} else {
						if (!class_.contains("Thesis")) {
							if (dataEntity.getDcTxtwords() != null)
								pay.setDocNumber(new BigDecimal(dataEntity
										.getDcTxtwords()));
							}
						
							if(class_.endsWith("Doc")){
								pay.setSubtype(((Doc)dataEntity).getSubtype());
							}
							if(class_.endsWith("DocUk")){
								pay.setSubtype(((DocUk)dataEntity).getSubtype());
							}
							
							pay.setAuthorId(dataEntity.getDcEditor2());
							pay.setTitle(title);
							updatePay(pay, userId, ip);
						
					}
					continue;
				}

			}
			
			
			//添加不足的稿酬日志
			if(StringUtils.isNotEmpty(authorId) && !hasAuthor){
				CcPay pay0 = new CcPay(class_, (Long)data.getPrimaryId(), new Date(), "djr");
				if(dataEntity.getDcTxtwords()!=null)
					pay0.setDocNumber(new BigDecimal(dataEntity
						.getDcTxtwords()));
				if(class_.endsWith("Doc")){
					pay0.setSubtype(((Doc)dataEntity).getSubtype());
				}
				if(class_.endsWith("DocUk")){
					pay0.setSubtype(((DocUk)dataEntity).getSubtype());
				}
				pay0.setAuthorId(authorId);
				pay0.setTitle(title);
				savePay(data,pay0,userId,ip);
			}
			
			if (StringUtils.isNotEmpty(dataEntity.getDcEditor1()) && !hasYsr){
				CcPay pay1 = new CcPay(class_, (Long)data.getPrimaryId(), new Date(), "ysr");
				if(type.contains("Uk"))
		    		pay1.setWorkitem("wgfyr");
				if(dataEntity.getDcTxtwords()!=null)
					pay1.setDocNumber(new BigDecimal(dataEntity
						.getDcTxtwords()));
				pay1.setAuthorId(dataEntity.getDcEditor1());
				pay1.setTitle(title);
				if(class_.endsWith("Doc")){
					pay1.setSubtype(((Doc)dataEntity).getSubtype());
				}
				if(class_.endsWith("DocUk")){
					pay1.setSubtype(((DocUk)dataEntity).getSubtype());
				}
				savePay(data,pay1,userId,ip);
				
			}
			
			if(StringUtils.isNotEmpty(dataEntity.getDcEditor2()) && !hasEsr){
				CcPay pay2 = new CcPay(class_, (Long)data.getPrimaryId(), new Date(), "esr");
				if(type.contains("Uk"))
		    		pay2.setWorkitem("wwscr");
				if(dataEntity.getDcTxtwords()!=null)
					pay2.setDocNumber(new BigDecimal(dataEntity
						.getDcTxtwords()));
				pay2.setAuthorId(dataEntity.getDcEditor2());
				pay2.setTitle(title);
				if(class_.endsWith("Doc")){
					pay2.setSubtype(((Doc)dataEntity).getSubtype());
				}
				if(class_.endsWith("DocUk")){
					pay2.setSubtype(((DocUk)dataEntity).getSubtype());
				}
				savePay(data,pay2,userId,ip);
			}
			
		} catch (JsonGenerationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
    
	public void updatePayGive(List<CcPay> ccPayList, String reGiveFlag, String reGiveMan, Date reGiveTime, String ip , Date begin, Date end) {
		Object[] ids = Collections2.transform(ccPayList, new Function<CcPay, Long>(){

			@Override
			public Long apply(CcPay arg0) {
				return arg0 != null ? arg0.getId() : 0;
			}
			
		}).toArray();
		
		int n = jdbcTemplate.update("update CC_PAY set RE_GIVE_FLAG = ?, RE_GIVE_MAN = ?, RE_GIVE_TIME = ?  where (REWARD_C_TIME between ? and ? and (REWARD is not null and REWARD>=0) and RE_GIVE_FLAG='N' and REWARD_FLAG='Y')" ,
					new Object[] { reGiveFlag, reGiveMan, reGiveTime ,begin, end}, new int[] {Types.VARCHAR, Types.VARCHAR, Types.DATE, Types.DATE, Types.DATE}
				);
		/*
		int n = jdbcTemplate.update("update ccpay set reGiveFlag = ?, reGiveMan = ?, reGiveTime = ?  where (rewardCTime between ? and ? and reward is not null and reward>=0 and reGiveFlag='N' and rewardFlag='Y')" ,
				new Object[] { reGiveFlag, reGiveMan, reGiveTime ,begin, end}, new int[] {Types.VARCHAR, Types.VARCHAR, Types.DATE, Types.DATE, Types.DATE}
			);
		*/
		CcSync log = new CcSync();
        log.setEn("dao.hb.CcPay");
        log.setKeyval("批量修改");
        log.setOper("U");
        log.setTmCreate(new Date());
        log.setUserid(reGiveMan);
        log.setIp(ip);			
        log.setDescription(String.format("修改了%d条记录，查询id:%s", n, Arrays.toString(ids)));
        log.setDcCreate(new Date());
        entityManager.persist(log);
	}

}
